1時間プログラミング 001 ダイスロール
概要
ダイスロールするコマンド
使い方
code:terminal
$ diceroll 1d6
1d6 = 3 (3)
$ diceroll 2d6
2d6 = 2 5 (7)
$ diceroll 3d100
3d100 = 95 34 17 (146)
実装
正規表現でロール数とサイコロを取得して、乱数で出目を作成する
コードを一部抜粋
code:diceroll.rs
struct DiceRoll {
roll_count: u32,
dice: u32,
}
impl TryFrom<&str> for DiceRoll {
type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let re = Regex::new(r"\A(\d+)dD(\d+)\z").unwrap(); let captures = re.captures(value).ok_or(anyhow!(
"invalid format: expect '<roll_count>d<dice>' (ex: '26d')"
))?;
// roll_count
let roll_count = captures.get(1).map(|m| m.as_str()).unwrap();
let roll_count: u32 = roll_count.parse()?;
if !(1..=10).contains(&roll_count) {
return Err(anyhow!("invalid roll count: expect between 1 and 10"));
}
// dice
let dice = captures.get(2).map(|m| m.as_str()).unwrap();
let dice: u32 = dice.parse()?;
if !(1..=100).contains(&dice) {
return Err(anyhow!("invalid dice: expect between 1 and 100"));
}
Ok(Self { roll_count, dice })
}
}
impl DiceRoll {
fn roll(&self) -> DiceRollResult {
let mut rng = rand::thread_rng();
let result = (0..self.roll_count)
.map(|_| rng.gen_range(1..=self.dice))
.collect();
DiceRollResult::new(result)
}
}
感想
最初はパーサコンビネータでロール数とサイコロを取得しようと思ったが、単純だし正規表現でいいやってなった
ユニットテストを書いたが、1時間プログラムの場合はなしでよいかもしれない